package com.inspur.edp.common.type;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.inspur.edp.common.type.constant.TypeConstant;
import com.inspur.edp.common.type.exception.TypeException;
import lombok.Data;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author lizhaorui
 * @description TODO
 * @date 2024/5/27 15:30
 */

@Data
public class Type {

    public final static String CLASS_NAME = "dslClass";

    public static final String CODE = "code";

    public static final String VIRTUAL = "virtual";

    public static final String CONSTRUCTOR_KIND = "constructorKind";

    public static final String ARRAY_ACCESS_KIND = "arrayAccessKind";

    public static final String NULL_VALUE_KIND = "nullValueKind";

    private String source;

    private String typeId;

    // 类名
    private String code;

    private String name;

    private String description;

    private String example;

    // 接口类全限定类型集合
    private List<TypeRefer> implementList;

    // 扩展全限定类名
    private TypeRefer extendType;

    private TypeKind typeKind = TypeKind.CLASS;

    // 枚举项, 仅枚举是用
    private List<EnumItem> enumItems;

    // 字段集合
    private List<Field> fields;

    // 方法集合
    private List<Method> methods;

    // 泛型类型全限定集合
    private List<String> genericTypeNames;

    // 当前类型运行时行为设置
    private Map<String, DecorationOption> decorationMap;

    // 是否动态结构
    private boolean virtual;

    public Field getField(String fieldCode) {
        Field field = this.tryGetField(fieldCode);
        if (field != null) {
            return field;
        } else {
            throw new TypeException(String.format("type source %s typeId %s not exists field %s", this.source, this.typeId, fieldCode));
        }
    }

    public Field tryGetField(String fieldCode) {
        for (Field fieldMd : fields) {
            if (fieldMd.getCode().equalsIgnoreCase(fieldCode)) {
                return fieldMd;
            }
        }
        return null;
    }

    public Method getMethod(String methodCode) {
        for (Method methodMd : methods) {
            if (methodMd.getCode().equalsIgnoreCase(methodCode)) {
                return methodMd;
            }
        }
        return null;
    }

    public void addDecoration(DecorationOption decoration) {
        if (this.decorationMap == null) {
            this.decorationMap = new HashMap<>();
        }
        this.decorationMap.put(decoration.getName(), decoration);
    }

    public TypeRefer buildTypeRefer() {
        return new TypeRefer(this.source, this.typeId);
    }

    public String getTypeOptCode() {
        return decorationMap.get(CLASS_NAME).getOptionMap().get(CODE);
    }

    @JsonIgnore
    public String getArrayAccessKind() {
        if (this.decorationMap == null) {
            return TypeConstant.DEFAULT_VALUE;
        }
        DecorationOption decorationOption = this.decorationMap.get(ARRAY_ACCESS_KIND);
        if (decorationOption == null) {
            return TypeConstant.DEFAULT_VALUE;
        } else {
            return decorationOption.getOptionMap().get(TypeConstant.KIND);
        }
    }

    @JsonIgnore
    public String getConstructorKind() {
        if (this.decorationMap == null) {
            return TypeConstant.DEFAULT_VALUE;
        }
        DecorationOption decorationOption = this.decorationMap.get(CONSTRUCTOR_KIND);
        if (decorationOption == null) {
            return TypeConstant.DEFAULT_VALUE;
        } else {
            return decorationOption.getOptionMap().get(TypeConstant.KIND);
        }
    }

    @JsonIgnore
    public DecorationOption getConstructorDecoration() {
        if (this.decorationMap == null) {
            return null;
        }
        return this.decorationMap.get(CONSTRUCTOR_KIND);
    }

    @JsonIgnore
    public void setTypeOptCode(String code) {
        if (this.decorationMap == null) {
            this.decorationMap = new HashMap<>();
        }
        DecorationOption dslClassDec = this.decorationMap.get(CLASS_NAME);
        if (dslClassDec == null) {
            dslClassDec = new DecorationOption(CLASS_NAME, new HashMap<>());
            this.addDecoration(dslClassDec);
        }
        dslClassDec.put(CODE, code);
    }

    @JsonIgnore
    public void setArrayAccessKind(String kind) {
        if (this.decorationMap == null) {
            this.decorationMap = new HashMap<>();
        }
        DecorationOption arrayAccessKind = this.decorationMap.get(ARRAY_ACCESS_KIND);
        if (arrayAccessKind == null) {
            arrayAccessKind = new DecorationOption(ARRAY_ACCESS_KIND, new HashMap<>());
            this.addDecoration(arrayAccessKind);
        }
        arrayAccessKind.put(TypeConstant.KIND, kind);
    }


    @JsonIgnore
    public String getNullValueKind() {
        if (this.decorationMap == null) {
            return TypeConstant.DEFAULT_VALUE;
        }
        DecorationOption decorationOption = this.decorationMap.get(NULL_VALUE_KIND);
        if (decorationOption == null) {
            return TypeConstant.DEFAULT_VALUE;
        } else {
            return decorationOption.getOptionMap().get(TypeConstant.KIND);
        }
    }


}
